package com.ruoyi.common.utils.minio;

import com.ruoyi.common.exception.ServiceException;
import io.minio.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class MinioTemplate {
    @Value("${minio.bucketName}")
    public String bucketName;
    @Autowired
    private MinioClient minioClient; //minio提供的Client接口

    /**
     * 判断桶是否存在,如果存在返回true,如果不存在返回false
     *
     * @param bucketName
     * @return
     */
    @SneakyThrows
    public Boolean existBucket(String bucketName) {
        boolean exist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!exist) {
            return false;
        }
        return true;

    }

    /**
     * 创建桶
     *
     * @param bucketName
     * @return
     */
    @SneakyThrows
    public void makeBucket(String bucketName) {
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 上传对象
     *
     * @param objectName
     * @param file
     * @return
     * @throws Exception
     */
    @SneakyThrows
    public void putObject(String objectName, MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) {
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(file.getContentType())
                    .stream(inputStream, file.getSize(), -1)
                    .build();
            minioClient.putObject(args);
        }
    }

    @SneakyThrows
    public void addFileToZip(String objectName, ZipOutputStream zipOut, String fileName) throws IOException {
        InputStream in = null;
        try {
            in = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName) // 替换为你的音频文件路径
                            .build());
            //是存储之前还是存储之后  可能是动态的 还是在存储之后吧  到处的时候去修改文件名称
            zipOut.putNextEntry(new ZipEntry(fileName)); // 将文件名称添加到 ZIP
            byte[] buffer = new byte[1024 * 10];
            int length;
            while ((length = in.read(buffer)) > 0) {
                zipOut.write(buffer, 0, length); // 写入 ZIP 输出流
                zipOut.flush(); // 刷新 ZipOutputStream，确保数据被写入
            }
            zipOut.closeEntry(); // 关闭当前 ZIP 条目
        } finally {
            if (in != null) {
                in.close(); // 关闭输入流
            }
        }
    }

    /**
     * 删除对象
     *
     * @param objectName
     * @return
     * @throws Exception
     */
    @SneakyThrows
    public boolean removeObject(String objectName) {
        boolean flag = existBucket(bucketName);
        if (flag) {
            RemoveObjectArgs args = RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build();
            minioClient.removeObject(args);
            return true;
        }
        return false;
    }

    /**
     * 获取对象信息
     *
     * @param objectName
     * @return
     * @throws Exception
     */
    @SneakyThrows
    public ObjectStat getMessage(String objectName) {
        boolean flag = existBucket(bucketName);
        System.out.println(flag == true);
        if (flag) {
            ObjectStat statObject = minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
            return statObject;
        }
        return null;
    }

    /**
     * 返回的文件路径,不会过期.
     *
     * @param objectName
     * @return
     */
    @SneakyThrows
    public String getObjectUrl(String objectName) {
        Boolean flag = existBucket(bucketName);
        String url = "";
        if (flag) {
            url = minioClient.getObjectUrl(bucketName, objectName);
        }
        return url;
    }

    public InputStream getInputStream(String objectName) {
        // 从 MinIO 获取音频文件
//        in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(filename).build());
        try {
            InputStream audioStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName) // 替换为你的音频文件路径
                            .build());
            return audioStream;
        } catch (Exception e) {
            throw new ServiceException("异常");
        }
    }

    /**
     * 从minio中下载文件
     *
     * @param filename
     * @param response
     */
    public void getObject(String filename, HttpServletResponse response) {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(filename).build());
            int length = 0;
            byte[] buffer = new byte[1024];
            out = response.getOutputStream();
            response.reset();
            response.addHeader("Content-Disposition",
                    " attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
            response.setContentType("application/octet-stream");
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}
